import 'dart:ui';

import 'package:imperius_insights/entity/project.dart';
import 'package:imperius_insights/modules/projects/viewmodels/colors.dart';
import 'package:imperius_insights/modules/projects/viewmodels/strings.dart';
import 'package:imperius_insights/portal/toolkits/date.dart';
import 'package:imperius_insights/portal/viewmodel.dart';

import 'staging.dart';

class Delay {
  Staging expectStaging;
  Staging actualStaging;

  Delay({ this.actualStaging, this.expectStaging });
}

class ProjectViewModel extends ViewModelBasal<Project> {

  ProjectViewModel(Project data) : super(data);

  String get pmo => data.pmo;

  String get name => data.name;

  String get cardTitle => '[${data.pmo}] - ${stagingToText(data.staging)}';

  Color get themeColor => stagingToColor(data.staging);

  String get humansPMLabel {
    return data.humansOfPM?.map((p) => p.name)?.join('; ');
  }

  String get humansRDLabel {
    return data.humansOfRD?.map((p) => p.name)?.join('; ');
  }

  String get humansQALabel {
    return data.humansOfQA?.map((p) => p.name)?.join('; ');
  }

  Delay get delay {
    final now = DateTime.now();
    final actualStaging = data.staging;
    final expectStaging = calcMilestoneStagingEarly(now);
    final previousDayExpectStaging = calcMilestoneStagingEarly(now.subtract(Duration(days: 1)));
    if (expectStaging.index <= actualStaging.index) {
      return null;
    }
    // 防止过早提醒（员工早上还未准备就绪工作）每天11点前，如果计划与实际状态序列差1 且 前一天计划状态为现在的实际状态，则忽略不计为delay警告
    if (DateTime.now().hour < 11 && expectStaging != Staging.PostPublish
        && (expectStaging.index == actualStaging.index + 1)
        && couldStagingContinuesFromPreviousDay(actualStaging, previousDayExpectStaging)) {
      return null;
    }
    return Delay(
        actualStaging: data.staging,
        expectStaging: expectStaging
    );
  }

  String get delayInfo {
    if (delay == null) {
      return null;
    }
    return '计划状态为 ${stagingToText(delay.expectStaging)}，实际状态为 ${stagingToText((delay.actualStaging))}';
  }

  String get jiraLink => data.linkJira;

  String get bugsLink => data.bugsLink;

  String get qtLink => data.qtLink;

  String get hiatus {
    if (data.staging == Staging.PostPublish) {
      return null;
    }
    final texts = <String>[];
    if (data.startDevDate == null || data.startDevDate.year == 1970) {
      texts.add('计划开发日期为空');
    }
    if (data.type != '任务' &&
        (data.startTestDate == null || data.startTestDate.year == 1970)) {
      texts.add('计划开始测试日期为空');
    }
    if (data.scheduledPublishDate == null ||
        data.scheduledPublishDate.year == 1970) {
      texts.add('计划发布日期为空');
    }
    return texts.join('\n');
  }

  Staging calcMilestoneStagingEarly(DateTime date) {
    if (data.actualPublishDate != null && isSameDay(date, data.actualPublishDate)) {
      return Staging.PostPublish;
    }

    if (isSameDay(data.startDevDate, date)) {
      return Staging.Develop;
    }

    if (data.startDevDate != null && data.endDevDate != null) {
      if (isDaySameOrBefore(data.startDevDate, date) &&
          isDaySameOrAfter(data.endDevDate, date)) {
        return Staging.Develop;
      }
    }

    if (isSameDay(data.startTestDate, date)) {
      return Staging.QATesting;
    }

    if (data.startTestDate != null && data.endTestDate != null) {
      if (data.type != '任务' &&
          isDaySameOrBefore(data.startTestDate, date) &&
          isDaySameOrAfter(data.endTestDate, date)) {
        return Staging.QATesting;
      }
    }

    if (data.startDevDate != null && date.isBefore(data.startDevDate)) {
      return Staging.Scheduled;
    }

    if (data.scheduledPublishDate != null && isDaySameOrBefore(date, data.scheduledPublishDate)) {
      return Staging.QATesting;
    }
    if (data.scheduledPublishDate != null && isDaySameOrAfter(date, data.scheduledPublishDate)) {
      return Staging.PostPublish;
    }
    return Staging.Unset;
  }

  Staging calcMilestoneStaging(DateTime date) {
    if (data.actualPublishDate != null && isSameDay(date, data.actualPublishDate)) {
      return Staging.PostPublish;
    }

    if (data.scheduledPublishDate != null && isSameDay(date, data.scheduledPublishDate)) {
      return Staging.PrePublish;
    }

    if (data.startDevDate != null && data.endDevDate != null) {
      if (data.type == '任务' && data.scheduledPublishDate != null) {
        if (isDaySameOrBefore(data.startDevDate, date) &&
            isDaySameOrAfter(data.scheduledPublishDate, date)) {
          return Staging.Develop;
        }
      }
      if (isDaySameOrBefore(data.startDevDate, date) &&
          isDaySameOrAfter(data.endDevDate, date)) {
        return Staging.Develop;
      }
    }

    if (data.startTestDate != null && data.endTestDate != null) {
      if (data.type != '任务' &&
          isDaySameOrBefore(data.startTestDate, date) &&
          isDaySameOrAfter(data.endTestDate, date)) {
        return Staging.QATesting;
      }
    }

    if (data.startDevDate != null && isDaySameOrBefore(date, data.startDevDate)) {
      return Staging.Scheduled;
    }

    if (data.scheduledPublishDate != null && isDaySameOrBefore(date, data.scheduledPublishDate)) {
      return Staging.PrePublish;
    }
    if (data.scheduledPublishDate != null && isDaySameOrAfter(date, data.scheduledPublishDate)) {
      return Staging.PostPublish;
    }
    return Staging.Unset;
  }
}